/*
 * @lc app=leetcode id=468 lang=cpp
 *
 * [468] Validate IP Address
 */

// @lc code=start
class Solution {
public:
    string validIPAddress(string IP) {
        if (isIPv4(IP)){
            return "IPv4";
        }
        if (isIpv6(IP)){
            return "IPv6";
        }
        return "Neither";
    }
    bool isIPv4(const string &IP){
        std::string num;
        std::vector<std::string> nums;
        for (int i = 0; i < IP.size(); ++i) {
            if (IP[i] == '.') {
                if (num.empty()){
                    return false;
                }
                nums.push_back(num);
                num.clear();
            } else {
                num.push_back(IP[i]);
            }
        }
        if (num.empty()) {
            return false;
        }
        nums.push_back(num);
        if (nums.size() != 4) {
            return false;
        }

        auto valid = [](const std::string &num) {
           if (num.size() > 3) {
               return false;
           }
           for (int i =0; i < num.size(); ++i) {
               if (!(num[i]>='0' && num[i] <= '9')){
                   return false;
               }
           }
           if (num[0] == '0') {
               if (num.size() == 1) {
                   return true;
               }
               return false;
           }
           int n = std::stoi(num);
           if (n <= 255) {
               return true;
           }
           return false;
        };
        for (auto num : nums) {
            if (!valid(num)){
                return false;
            }
        }        
        return true;  
    }

    bool isIpv6(const string &IP) {
        std::string num;
        std::vector<std::string> nums;
        for (int i = 0; i < IP.size(); ++i) {
            if (IP[i] == ':') {
                if (num.empty()){
                    return false;
                }
                nums.push_back(num);
                num.clear();
            } else {
                num.push_back(IP[i]);
            }
        }
        if (num.empty()) {
            return false;
        }
        nums.push_back(num);
        if (nums.size() != 8) {
            return false;
        }   
         auto valid = [](const std::string &num) {
           if (num.size() > 4) {
               return false;
           }
           for (int i =0; i < num.size(); ++i) {
               if ((num[i]>='0' && num[i] <= '9') || (num[i] >= 'a' && num[i] <= 'f') || (num[i] >= 'A' && num[i] <= 'F')){
                   continue;
               } else {
                   return false;
               }
           }
           return true;
        };
        for (auto num : nums) {
            if (!valid(num)){
                return false;
            }
        }        
        return true;  
    }
};
// @lc code=end

